#include "../inc/segmenttree.h"
#include "../inc/boundingbox.h"

SegmentTree::SegmentTree()
{
	segment = new Segment();
	son = NULL;
	brother = NULL;
}

SegmentTree::SegmentTree(const SegmentTree &_tree)
{
	segment->clear();
	segment = _tree.segment;
	color = _tree.color;
	name = _tree.name;
	
	if ( _tree.son != NULL )
	{
		SegmentTree* mySon = new SegmentTree();
		mySon->copy( _tree.son );
		son = mySon;
	}
	
	else
	{
		son = NULL;
	}
	
	if ( _tree.brother != NULL )
	{
		SegmentTree* myBro = new SegmentTree();
		myBro->copy( _tree.brother );
		brother = myBro;
	}
	
	else
	{
		brother = NULL;
	}
}

SegmentTree::~SegmentTree()
{
	/* Recursive destroying function :
	   We destroy every brother and every son of the node
	   and then, we destroy the node.
	*/
	if ( brother != NULL )
		brother->~SegmentTree();

	if ( son != NULL )
		son->~SegmentTree();
	
	color.clear();
	name.clear();
	segment->clear();
}

SegmentTree& SegmentTree::operator = ( const SegmentTree& _tree )
{
	segment->clear();
	segment = _tree.segment;
	color = _tree.color;
	name = _tree.name;
	
	if ( _tree.son != NULL )
	{
		SegmentTree* mySon = new SegmentTree();
		mySon->copy( _tree.son );
		son = mySon;
	}
	
	else
	{
		son = NULL;
	}
	
	if ( _tree.brother != NULL )
	{
		SegmentTree* myBro = new SegmentTree();
		myBro->copy( _tree.brother );
		brother = myBro;
	}
	
	else
	{
		brother = NULL;
	}
	
	return *this;
}

Segment* SegmentTree::getSegment()
{
	return segment;
}

SegmentTree* SegmentTree::getSon()
{
	return son;
}

SegmentTree* SegmentTree::getBrother()
{
	return brother;
}

Vector3D SegmentTree::getColor()
{
	return color;
}

string SegmentTree::getName()
{
	return name;
}

double* SegmentTree::getColorArray()
{
	return color.getArray();
}

int SegmentTree::getNbSons()
{
	if ( son == NULL )
		return 0;
	
	int cpt = 0;
	
	for ( SegmentTree* node = son ; node != NULL ; node = node->getBrother() )
		cpt++;
	
	return cpt;
}

int SegmentTree::getNbBrothers()
{
	if ( brother == NULL )
		return 0;
	
	int cpt = 0;
	
	for ( SegmentTree* it = brother ; it != NULL ; it = it->getBrother() )
		cpt++;
	
	return cpt;
}

double SegmentTree::getMaxDepth()
{
	/* C'est a l'envers parce qu'on cherche la PROFONDEUR max, c'est a dire l'endroit ou la valeur est la plus petite. */
	if ( son == NULL )
	{
		/* The calling node is a leaf. End of the recursion. */
		return getSegment()->getDepth();
	}
	
	double min = INT_MAX;
	double rslt;
	
	if ( brother != NULL )
	{
		rslt = brother->getMaxDepth();
	
		if ( rslt < min )
			min = rslt;
	}
	
	rslt = son->getMaxDepth();
	
	if ( rslt < min )
		min = rslt;
	
	return min;
}

double SegmentTree::getMinDepth()
{
	/* C'est a l'envers parce qu'on cherche la PROFONDEUR min, c'est a dire l'endroit ou la valeur est la plus grande. */
	if ( son == NULL )
	{
		/* The calling node is a leaf. End of the recursion. */
		return getSegment()->getDepth();
	}
	
	double max = INT_MIN;
	double rslt;
	
	if ( brother != NULL )
	{
		rslt = brother->getMaxDepth();
	
		if ( rslt > max )
			max = rslt;
	}
	
	rslt = son->getMaxDepth();
	
	if ( rslt > max )
		max = rslt;
	
	return max;
}

void SegmentTree::setSegment(Segment* _s)
{
	segment = _s;
}

void SegmentTree::setSon(SegmentTree *_son)
{
	son = _son;
}

void SegmentTree::setBrother(SegmentTree *_brother)
{
	brother = _brother;
}

void SegmentTree::setColor(Vector3D _color)
{
	color = _color;
}

void SegmentTree::setName(string _name)
{
	name = _name;
}

void SegmentTree::addSon(SegmentTree *_st)
{
	/* If the node doesn't have any sons yet, we just make the son pointer point on the _st node. */
	if ( son == NULL )
		son = _st;
	
	else
	{
		/* We add the _st node as a brother of the last son of the node. */
		SegmentTree* it = son;
		
		while ( it->getBrother() != NULL )
		{
			it = it->getBrother();
		}
		
		it->setBrother( _st );
	}
}

void SegmentTree::addBrother(SegmentTree *_st)
{
    if ( brother == NULL )
	{
		/* The node doesn't have any brothers. */
		if ( segment->getVerts().empty() )
		{
			/* The node is an empty node, it is a root. We just set the root's segment. */
			segment = _st->getSegment();
			return;
		}
		
		else
		{
			brother = _st;
			return;
		}
	}

    else
    {
            /* We add the _st node as a brother of the last son of the node. */
            SegmentTree* it = brother;

            while ( it->getBrother() != NULL )
            {
                    it = it->getBrother();
            }

            it->setBrother( _st );
    }
}

void SegmentTree::clear()
{
	segment->clear();
	color.clear();
	name.clear();
	
	if ( son != NULL )
		son->clear();
	
	if ( brother != NULL )
		brother->clear();
}

void SegmentTree::copy(SegmentTree *_tree)
{
	segment->clear();
	segment = _tree->getSegment();
	color = _tree->getColor();
	name = _tree->getName();
	
	if ( _tree->getSon() != NULL )
	{
		SegmentTree* mySon = new SegmentTree();
		mySon->copy( _tree->getSon() );
		son = mySon;
	}
	
	else
	{
		son = NULL;
	}
	
	if ( _tree->getBrother() != NULL )
	{
		SegmentTree* myBro = new SegmentTree();
		myBro->copy( _tree->getBrother() );
		brother = myBro;
	}
	
	else
	{
		brother = NULL;
	}
}

bool SegmentTree::intersects(SegmentTree *_s)
{
	return segment->intersects( _s->getSegment() );
}

int SegmentTree::intersectsQuantity(SegmentTree *_s)
{
	return segment->intersectsQuantity( _s->getSegment() );
}

void SegmentTree::merge(SegmentTree *_s)
{
	segment->addSegment( _s->getSegment() );
	addSon( _s->getSon() );
}

void SegmentTree::createFromMap_LeEq_RecursivePart ( SegmentList& _list, Segment* _s )
{	
	SegmentList sons;
	Segment*    maxDepthSegment;
	
	/* In a general way, every time a tree node is created, the corresponding segment is erased in the _list list in order to treat each segment only one time. */
	
	/* We create a list of the potential sons of the _s segment contained in the list _list. !!! This sons list will contain the direct sons and the non direct ones !!! */
	for ( list<Segment*>::iterator it = _list.getBegin() ; it != _list.getEnd() ; it++ )
	{
		if ( (*it) != _s && _s->contains( (*it) ) )
		{
				sons.addSegment( (*it) );
		}
	}
	

	/* While there is some potential directs sons. */
	while ( !sons.getSegments().empty() )
	{
		/* We extract the segment that has the maximum depth from the sons list. */
		maxDepthSegment = sons.extractMaximumDepth();
		
		if ( _list.contains( maxDepthSegment ) )
		{
			/* We immediately remove this segment from the _list list in order to treat it only once. */
			_list.removeSegment( maxDepthSegment );
	
			/* We create a node from this segment. */
			SegmentTree* toAdd = new SegmentTree();
			toAdd->setSegment( maxDepthSegment );
	
			/* And add it as a son of the node which called this method. */
			addSon( toAdd );
	
			/* Finally we launch the recursion from the segment we found. */
			toAdd->createFromMap_LeEq_RecursivePart( _list, maxDepthSegment );
		}
		
		else
			sons.removeSegment( maxDepthSegment );
	}
}

void SegmentTree::createFromMap_LeEq( double _thresh, Mesh _mesh, Map _map)
{
	SegmentList list;
	Segment*    segment;
	
	/* We first compute a list of all the segment on the mesh that verify the criteria. */
	list.createFromMap_LeEq( _thresh, _mesh, _map );
	
	/* We then create a tree from this list according to the inclusion criteria.
	   As soon as we create a node from a segment in the list, this segment is erased from this list.
	*/
	/* While some segments are still non processed (i.e. they are still in the list). */
	while ( !list.getSegments().empty() )
	{
		/* We exrtract the segment of maximum depth from the list. */
		segment = list.extractMaximumDepth();

		/* Then we create a node from this segment and add it as the root brother (the root is the segment tree object which calls this method). */
		SegmentTree* toAdd = new SegmentTree();
		toAdd->setSegment( segment );
		addBrother( toAdd );

		if ( brother != NULL )
			/* Finally, we launch a recursive step to find and set every sons of the segment we just added to the root. */
			toAdd->createFromMap_LeEq_RecursivePart( list, segment );
		
		else
			this->createFromMap_LeEq_RecursivePart( list, segment );
	}	
}

void SegmentTree::createFromMap_GrEq_RecursivePart ( SegmentList& _list, Segment* _s )
{	
	SegmentList sons;
	Segment*    minDepthSegment;
	
	/* In a general way, every time a tree node is created, the corresponding segment is erased in the _list list in order to treat each segment only one time. */
	
	/* We create a list of the potential sons of the _s segment contained in the list _list. !!! This sons list will contain the direct sons and the non direct ones !!! */
	for ( list<Segment*>::iterator it = _list.getBegin() ; it != _list.getEnd() ; it++ )
	{
		if ( (*it) != _s && _s->contains( (*it) ) )
		{
				sons.addSegment( (*it) );
		}
	}
	

	/* While there is some potential directs sons. */
	while ( !sons.getSegments().empty() )
	{
		/* We extract the segment that has the maximum depth from the sons list. */
		minDepthSegment = sons.extractMinimumDepth();
		
		if ( _list.contains( minDepthSegment ) )
		{
			/* We immediately remove this segment from the _list list in order to treat it only once. */
			_list.removeSegment( minDepthSegment );
	
			/* We create a node from this segment. */
			SegmentTree* toAdd = new SegmentTree();
			toAdd->setSegment( minDepthSegment );
	
			/* And add it as a son of the node which called this method. */
			addSon( toAdd );
	
			/* Finally we launch the recursion from the segment we found. */
			toAdd->createFromMap_GrEq_RecursivePart( _list, minDepthSegment );
		}
		
		else
			sons.removeSegment( minDepthSegment );
	}
}

void SegmentTree::createFromMap_GrEq( double _thresh, Mesh _mesh, Map _map)
{
	SegmentList list;
	Segment*    segment;
	
	/* We first compute a list of all the segment on the mesh that verify the criteria. */
	list.createFromMap_GrEq( _thresh, _mesh, _map );
	
	/* We then create a tree from this list according to the inclusion criteria.
	   As soon as we create a node from a segment in the list, this segment is erased from this list.
	*/
	/* While some segments are still non processed (i.e. they are still in the list). */
	while ( !list.getSegments().empty() )
	{
		/* We exrtract the segment of maximum depth from the list. */
		segment = list.extractMinimumDepth();

		/* Then we create a node from this segment and add it as the root brother (the root is the segment tree object which calls this method). */
		SegmentTree* toAdd = new SegmentTree();
		toAdd->setSegment( segment );
		addBrother( toAdd );

		/* Finally, we launch a recursive step to find and set every sons of the segment we just added to the root. */
		toAdd->createFromMap_GrEq_RecursivePart( list, segment );
	}	
}

void SegmentTree::createFromMap(int _criteria, double _thresh, Mesh _mesh, Map _map)
{
	if ( _criteria == LESSER_EQUAL )
		createFromMap_LeEq( _thresh, _mesh, _map );
	
	if ( _criteria == GREATER_EQUAL )
		createFromMap_GrEq( _thresh, _mesh, _map );
}

bool SegmentTree::matches_BBoxX( BoundingBox _refBBox, SegmentTree *_target, BoundingBox _targetMeshBBox, int _distMax )
{
	BoundingBox targetBBox;
	targetBBox.create( _target->getSegment() );
	targetBBox.convertsTo( _targetMeshBBox );
	
	return _refBBox.matchX( targetBBox, _distMax );
}

bool SegmentTree::matches_BBoxY( BoundingBox _refBBox, SegmentTree *_target, BoundingBox _targetMeshBBox, int _distMax )
{
	BoundingBox targetBBox;
	targetBBox.create( _target->getSegment() );
	targetBBox.convertsTo( _targetMeshBBox );
	
	return _refBBox.matchY( targetBBox, _distMax );
}

bool SegmentTree::matches_BBoxZ( BoundingBox _refBBox, SegmentTree *_target, BoundingBox _targetMeshBBox, int _distMax )
{
	BoundingBox targetBBox;
	targetBBox.create( _target->getSegment() );
	targetBBox.convertsTo( _targetMeshBBox );
	
	return _refBBox.matchZ( targetBBox, _distMax );
}

bool SegmentTree::matches_BBoxBotX(BoundingBox _refBBox, SegmentTree *_target, BoundingBox _targetMeshBBox, int _distMax)
{
	BoundingBox targetBBox;
	targetBBox.create( _target->getSegment() );
	targetBBox.convertsTo( _targetMeshBBox );
	
	return _refBBox.matchBotX( targetBBox, _distMax );
}

bool SegmentTree::matches_BBoxBotY(BoundingBox _refBBox, SegmentTree *_target, BoundingBox _targetMeshBBox, int _distMax)
{
	BoundingBox targetBBox;
	targetBBox.create( _target->getSegment() );
	targetBBox.convertsTo( _targetMeshBBox );
	
	return _refBBox.matchBotY( targetBBox, _distMax );
}

bool SegmentTree::matches_BBoxBotZ(BoundingBox _refBBox, SegmentTree *_target, BoundingBox _targetMeshBBox, int _distMax)
{
	BoundingBox targetBBox;
	targetBBox.create( _target->getSegment() );
	targetBBox.convertsTo( _targetMeshBBox );
	
	return _refBBox.matchBotZ( targetBBox, _distMax );
}

bool SegmentTree::matches_BBoxTopX(BoundingBox _refBBox, SegmentTree *_target, BoundingBox _targetMeshBBox, int _distMax)
{
	BoundingBox targetBBox;
	targetBBox.create( _target->getSegment() );
	targetBBox.convertsTo( _targetMeshBBox );
	
	return _refBBox.matchTopX( targetBBox, _distMax );
}

bool SegmentTree::matches_BBoxTopY(BoundingBox _refBBox, SegmentTree *_target, BoundingBox _targetMeshBBox, int _distMax)
{
	BoundingBox targetBBox;
	targetBBox.create( _target->getSegment() );
	targetBBox.convertsTo( _targetMeshBBox );
	
	return _refBBox.matchTopY( targetBBox, _distMax );
}

bool SegmentTree::matches_BBoxTopZ(BoundingBox _refBBox, SegmentTree *_target, BoundingBox _targetMeshBBox, int _distMax)
{
	BoundingBox targetBBox;
	targetBBox.create( _target->getSegment() );
	targetBBox.convertsTo( _targetMeshBBox );
	
	return _refBBox.matchTopZ( targetBBox, _distMax );
}

bool SegmentTree::matches_Depth(SegmentTree *_target, int _distMax)
{
	float distance = getMaxDepth() - _target->getMaxDepth();
	if ( distance < 0 )
		distance *= -1;
	
	if (  distance < _distMax )
		return true;
	
	else return false;
}

bool SegmentTree::matches_Area(double _areaRef, SegmentTree *_target, Mesh *_targetMesh, double _areaTargetMesh, double _distMax)
{
	float distance = _areaRef - _target->getSegment()->getTriangulatedAreaConverted( _targetMesh, _areaTargetMesh );
	if ( distance < 0 )
		distance *= -1;
	
	if (  distance < _distMax )
		return true;
	
	else return false;
}

bool SegmentTree::matches_Intersection(SegmentTree *_target)
{
	return segment->intersects( _target->getSegment() );
}

bool SegmentTree::matches_Distance(Mesh *_refMesh, SegmentTree *_target, int _distMax)
{
	/* See the SegmentTreeList::getMatchBy_Distance for more explanations. These methods are very similar. */
	int* mark = (int*) calloc ( _refMesh->getNVerts(), sizeof(int) );
	list<Vertex*>	liste;
	
	liste = getSegment()->getBoundary( mark );
	
	while ( !liste.empty() )
	{
		Vertex* v = liste.front();
		liste.pop_front();
		
		if ( mark[ v->getID() ] <= _distMax )
		{
			for ( int i = 0 ; i < (int)v->getEdges().size() ; i++ )
			{
				Vertex* neighbour = v->getIEdge( i )->getHead();
				
				if ( _target->getSegment()->contains( neighbour ) )
				{
					return true;
				}
				
				mark [ neighbour->getID() ] = mark [ v->getID() ] + 1;
				liste.push_back( neighbour );
			}
		}
	}
	
	return false;
}

int SegmentTree::getMatchScore(Mesh *_refMesh, SegmentTree *_target, Mesh *_targetMesh)
{
	BoundingBox bboxRefMesh;
	BoundingBox bboxTargetMesh;
	BoundingBox bboxNode;
	int score = 0;
	
	bboxRefMesh.create( _refMesh );
	bboxTargetMesh.create( _targetMesh );
	bboxNode.create( segment );
	bboxNode.convertsTo( bboxRefMesh );
	
	/* If a criteria is verified. */
	if ( matches_Distance( _refMesh, _target, 5 ) )
		score += 10; /* We increment the score by a certain weight. */
	
	if ( matches_Intersection( _target ) )
		score += 3;
	
	if ( matches_Area( segment->getTriangulatedAreaConverted( _refMesh, _refMesh->triangulatedArea() ), _target, _targetMesh, _targetMesh->triangulatedArea(), 0.1 ) )
		score += 1;
	
	if ( matches_Depth( _target ) )
		score += 1;
	
	if ( matches_BBoxBotX( bboxNode, _target, bboxTargetMesh, 5 ) )
		score += 3;
	
	if ( matches_BBoxBotY( bboxNode, _target, bboxTargetMesh, 5 ) )
		score += 3;
	
	if ( matches_BBoxBotZ( bboxNode, _target, bboxTargetMesh, 5 ) )
		score += 3;
	
	if ( matches_BBoxBotX( bboxNode, _target, bboxTargetMesh, 5 ) )
		score += 2;
	
	if ( matches_BBoxBotY( bboxNode, _target, bboxTargetMesh, 5 ) )
		score += 2;
	
	if ( matches_BBoxBotZ( bboxNode, _target, bboxTargetMesh, 5 ) )
		score += 2;
	
	if ( matches_BBoxTopX( bboxNode, _target, bboxTargetMesh, 5 ) )
		score += 2;
	
	if ( matches_BBoxTopY( bboxNode, _target, bboxTargetMesh, 5 ) )
		score += 2;
	
	if ( matches_BBoxTopZ( bboxNode, _target, bboxTargetMesh, 5 ) )
		score += 2;
	
	return score;
}

void SegmentTree::morphologicalDilatation(Mesh _mesh, int _size)
{
	segment->morphologicalDilatation( _mesh, _size );
}

void SegmentTree::morphologicalDilatation(Mesh* _mesh, int _size)
{
	segment->morphologicalDilatation( _mesh, _size );
}

void SegmentTree::morphologicalErosion(Mesh _mesh, int _size)
{
	segment->morphologicalErosion( _mesh, _size );
}

void SegmentTree::morphologicalErosion(Mesh* _mesh, int _size)
{
	segment->morphologicalErosion( _mesh, _size );
}

//void SegmentTree::morphologicalClosing(Mesh *_mesh, int _thresh)
//{
//	/* We dilate every ancester of the tree. */
//	for ( SegmentTree* it = this ; it != NULL ; it = it->getBrother() )
// 		it->morphologicalDilatation( _mesh, _thresh );
	
//	/* For each ancester of the tree. */
//	for ( SegmentTree* it = this ; it != NULL ; it = it->getBrother() )
//	{
//		/* We look if it intersects with another ancestor. */
//		for ( SegmentTree* it2 = it->getBrother() ; it2 != NULL ; it2 = it2->getBrother() )
//		{
//			if ( it->intersects( it2 ) )
//			{
//				/* Then we have to merge the two segments : all the vertex of it2 will be added to it, it will then be filtered to have uniques vertex in it. Finally the it sons will be added the it2 ones. */
//				it->merge( it2 );
				
//				/* Then we have to suppres it2 from the tree. */
//				it = SegmentTree::removeNode( it, it2 ); /* Even if it is not the first brother in the tree this works noramlly. */
//			}
//		}
//	}
	
//	/* We erode every ancester of the tree. */
//	for ( SegmentTree* it = this ; it != NULL ; it = it->getBrother() )
// 		it->morphologicalErosion( _mesh, _thresh );
//}

void SegmentTree::display( int _mode, double _r, double _g, double _b )
{
	if ( _mode == OWN_COLOR )
		segment->display( FACES, getColor().getX(), getColor().getY(), getColor().getZ() );
	
	if ( _mode == OTHER_COLOR )
		segment->display( FACES, _r, _g, _b );
	
	if ( _mode == MESH_COLOR )
		segment->display();
}

void SegmentTree::displaySons(int _mode, double _r, double _g, double _b)
{
    SegmentTree* node = NULL;

    for ( node = this->getSon() ; node != NULL ; node = node->getBrother() )
    {
        node->display( _mode, _r, _g, _b );
    }
}

void SegmentTree::displayBrotherhood(int _mode, double _r, double _g, double _b)
{
    SegmentTree* node = NULL;

	if ( _mode != PICKING )
	{
		for ( node = this ; node != NULL ; node = node->getBrother() )
		{
			node->display( _mode, _r, _g, _b );
		}
	}
	
	else
	{
		int i = 0;
		
		for ( node = this ; node != NULL ; node = node->getBrother() )
		{
			glLoadName(i);
			node->display();
			i++;
		}
	}
}

SegmentTree* SegmentTree::removeNode(SegmentTree *_firstBrother, SegmentTree *_toRemove)
{
	if ( _firstBrother == _toRemove )
	{	
		_firstBrother = _firstBrother->getBrother();
		return _firstBrother;
	}
	
	else
	{
		SegmentTree* it = NULL;
		
		for ( it = _firstBrother ; it != NULL ; it = it->getBrother() )
		{
			if ( it->getBrother() == _toRemove )
			{
				it->setBrother( _toRemove->getBrother() );
				/*
				_toRemove->~SegmentTree();
				*/
				return _firstBrother;
			}
		}
	}
	
	return _firstBrother;
}

SegmentTree* SegmentTree::filterSize(SegmentTree *_tree, int _thresh)
{
	for ( SegmentTree* it = _tree ; it != NULL ; it = it->getBrother() )
	{
		if ( (int)it->getSegment()->getVerts().size() < _thresh )
		{
			_tree = SegmentTree::removeNode( _tree, it );
		}
	}
	
	return _tree;
}

SegmentTree* SegmentTree::filterArea( Mesh* _mesh, SegmentTree *_tree, double _thresh)
{
	for ( SegmentTree* it = _tree ; it != NULL ; it = it->getBrother() )
	{
		if ( it->getSegment()->getTriangulatedAreaConverted( _mesh, _mesh->triangulatedArea() ) < _thresh )
		{
			_tree = SegmentTree::removeNode( _tree, it );
		}
	}
	
	return _tree;
}

SegmentTree* SegmentTree::splitTooBigSegments(Mesh *_mesh, SegmentTree* _tree, double _thresh)
{
	double meshArea = _mesh->triangulatedArea();
	
	/* If the first brother is too big. */
	while ( _tree->getSegment()->getTriangulatedAreaConverted( _mesh, meshArea ) > _thresh && _tree->getSon() != NULL )
	{
		SegmentTree* it = NULL;
		SegmentTree* bro = _tree->getBrother();
		
		cout<<"Youhou"<<endl;
		
		if ( _tree->getSon() != NULL )
		{
			_tree = _tree->getSon();
			/* Maybe we should clear the deleted node. */
			
			for ( it = _tree ; it->getBrother() != NULL ; it = it->getBrother() )
				;
			it->setBrother( bro );
		}
	}
	
	/* For every ancester of the tree. */
	for ( SegmentTree* it = _tree ; it != NULL ; it = it->getBrother() )
	{
		SegmentTree* it2 = it->getBrother();
		
		/* If one is too big. And has a son. */
		while ( it2 != NULL && it2->getSegment()->getTriangulatedAreaConverted( _mesh, meshArea ) > _thresh && it2->getSon() != NULL )
		{
			SegmentTree* it3 = NULL;
			SegmentTree* bro = it2->getBrother();
			it->setBrother( it2->getSon() );
			
			for ( it3 = it->getBrother() ; it3->getBrother() != NULL ; it3 = it3->getBrother() )
				;
			it3->setBrother( bro );
			
			it2 = it->getBrother();
		}
	}
	
	return _tree;
}

SegmentTree* SegmentTree::morphologicalClosing(SegmentTree *_tree, Mesh *_mesh, int _thresh)
{
	/* We dilate every ancester of the tree. */
	for ( SegmentTree* it = _tree; it != NULL ; it = it->getBrother() )
 		it->morphologicalDilatation( _mesh, _thresh );
	
	/* For each ancester of the tree. */
	for ( SegmentTree* it = _tree ; it != NULL ; it = it->getBrother() )
	{
		/* We look if it intersects with another ancestor. */
		for ( SegmentTree* it2 = _tree ; it2 != NULL ; it2 = it2->getBrother() )
		{
			if ( it != it2 && it->intersects( it2 ) )
			{
				/* Then we have to merge the two segments : all the vertex of it2 will be added to it, it will then be filtered to have uniques vertex in it. Finally the it sons will be added the it2 ones. */
				it->merge( it2 );
				
				/* Then we have to suppres it2 from the tree. */
				if ( it2 == _tree )
				{
					_tree = SegmentTree::removeNode( _tree, it2 );
					it2 = _tree;
				}
				
				else
					_tree = SegmentTree::removeNode( _tree, it2 );
			}
		}
	}
	
	/* We erode every ancester of the tree. */
	for ( SegmentTree* it = _tree ; it != NULL ; it = it->getBrother() )
 		it->morphologicalErosion( _mesh, _thresh );
	
	return _tree;
}

void SegmentTree::print( Mesh* _mesh )
{
	cout<<"Elemnt Informations :"<<endl;
	cout<<"Name of the element : \""<<getName()<<"\""<<endl;
	cout<<"Color of the element [r,g,b] : ["<<getColor().getX()<<","<<getColor().getY()<<","<<getColor().getZ()<<"]"<<endl;
	cout<<"Segment ID : "<<getSegment()->getID()<<endl;
	cout<<"Nb vertices in the segment : "<<getSegment()->getVerts().size()<<endl;
	
	if ( _mesh != NULL )
		cout<<"Area of the segment : "<<getSegment()->getTriangulatedArea( _mesh );
	
	cout<<"Etc. To add some informations in this display go and add some code in the SegmentTree::print method"<<endl;
}
